package control;
import java.util.Arrays;

public class Simulator implements Hardware, Runnable {

	private int[] m_heatpumps;
	private double[] m_vents; //m_sensors;
	
	private final double RATE = 0.01;
	private final double HOT = 100, COLD=50;
	private double[] m_temperature;
	double m_outdoor = 90;
	
	
	public Simulator(int numberOfFloors, double setPoint) {
		if (numberOfFloors % 3 != 0)
		throw new RuntimeException("Illegal value");
		m_heatpumps = new int[numberOfFloors/3];
		m_vents = new double[numberOfFloors];
		// m_sensors = new double[numberOfFloors];
		m_temperature = new double[numberOfFloors];
	
		Arrays.fill(m_temperature, 70);
		Thermometer.SetThermometerFVTerms(setPoint);
		new Thread(this).start();
	}
	
	public int getHeatPumpState(int heatPump) {
		return m_heatpumps[heatPump-1];
	}
	
	public void setHeatPumpState(int heatPump, int state) {
		switch (state) {
			case OFF: case HEATING: case COOLING:
			m_heatpumps[heatPump-1] = state; break;
			default:
		throw new RuntimeException("Illegal value");
		}
	}
	
	public int getNumberOfHeatPumps() {
		return m_heatpumps.length;
	}
	
	public double getVentState(int vent) {
		return m_vents[vent-1];
	}
	
	public void setVentState(int vent, double state) {
		m_vents[vent-1] = state;
	}
	
	public double getTemperature(int sensor) {
		return m_temperature[sensor-1];
	}
	
	public void run() {
		while (true) {
			for (int i=0; i<m_temperature.length; ++i) {
				double temp = m_temperature[i];
				// Heating and cooling, and heat rising
				switch (state(i)) {
				case HEATING:
				temp += (HOT-temp)*RATE; break;
				case COOLING:
				temp += (COLD-temp)*RATE; break;
				case OFF:
				temp += (i+1)*0.005; break;
				}
				// Outdoor leakage
				temp += (m_outdoor-temp)*RATE/2;
				m_temperature[i] = temp;
			}
			try {Thread.sleep(1000);}
			catch (InterruptedException ie) { return;}
		}
	}
	
	private int state(int floor) {
		if (getVentState(floor + 1) > 0)
		return getHeatPumpState(floor/3 + 1);
		else
		return OFF;
	}

}
